import asyncio
from typing import Optional
from collections import defaultdict
import heapq
import time

from app.models.task.task_data import Task, TaskPriority


class PriorityTaskItem:
    """优先级任务项，用于堆队列"""

    def __init__(self, task: Task):
        self.task = task
        self.priority = -task.priority.value  # 负数使得高优先级排在前面
        self.timestamp = time.time()  # 用于相同优先级时的FIFO排序

    def __lt__(self, other):
        if self.priority != other.priority:
            return self.priority < other.priority
        return self.timestamp < other.timestamp


class AsyncTaskQueue:
    """异步任务队列 - 支持优先级和背压控制"""

    def __init__(self, maxsize: int = 1000):
        self._queue = asyncio.PriorityQueue(maxsize=maxsize)
        self._size = 0
        self._maxsize = maxsize

    async def put(self, task: Task) -> None:
        """添加任务到队列"""
        item = PriorityTaskItem(task)
        await self._queue.put(item)
        self._size += 1

    def put_nowait(self, task: Task) -> None:
        """非阻塞添加任务到队列"""
        item = PriorityTaskItem(task)
        self._queue.put_nowait(item)
        self._size += 1

    async def get(self) -> Task:
        """从队列中获取最高优先级的任务"""
        item = await self._queue.get()
        self._size -= 1
        return item.task

    async def get_with_timeout(self, timeout: float = 0.1) -> Optional[Task]:
        """带超时的获取任务"""
        try:
            item = await asyncio.wait_for(self._queue.get(), timeout=timeout)
            self._size -= 1
            return item.task
        except asyncio.TimeoutError:
            return None

    def empty(self) -> bool:
        """检查队列是否为空"""
        return self._queue.empty()

    def full(self) -> bool:
        """检查队列是否已满"""
        return self._queue.full()

    def size(self) -> int:
        """获取队列大小"""
        return self._size

    @property
    def maxsize(self) -> int:
        """获取最大队列大小"""
        return self._maxsize

    def task_done(self):
        """标记任务完成"""
        self._queue.task_done()


# 为了向后兼容，保留原来的同步接口
class TaskQueue:
    """任务队列 - 支持优先级（兼容旧版本）"""

    def __init__(self, maxsize: int = 1000):
        self._async_queue = AsyncTaskQueue(maxsize)

    def put(self, task: Task) -> None:
        """添加任务到队列"""
        try:
            self._async_queue.put_nowait(task)
        except asyncio.QueueFull:
            raise RuntimeError("任务队列已满")

    def get(self) -> Optional[Task]:
        """从队列中获取最高优先级的任务（非阻塞）"""
        try:
            # 创建一个临时事件循环来处理异步操作
            loop = asyncio.get_event_loop()
            if loop.is_running():
                # 如果已有运行中的事件循环，使用非阻塞方式
                return None if self._async_queue.empty() else self._get_sync()
            else:
                return loop.run_until_complete(self._async_queue.get_with_timeout(0))
        except:
            return None

    def _get_sync(self) -> Optional[Task]:
        """同步获取任务的辅助方法"""
        if not self._async_queue.empty():
            try:
                item = self._async_queue._queue.get_nowait()
                self._async_queue._size -= 1
                return item.task
            except:
                return None
        return None

    def empty(self) -> bool:
        """检查队列是否为空"""
        return self._async_queue.empty()

    def size(self) -> int:
        """获取队列大小"""
        return self._async_queue.size()

    def clear(self) -> None:
        """清空队列"""
        while not self._async_queue.empty():
            try:
                self._async_queue._queue.get_nowait()
                self._async_queue._size -= 1
            except:
                break

    @property
    def async_queue(self) -> AsyncTaskQueue:
        """获取异步队列实例"""
        return self._async_queue
